package cn.itsub.sodo.core.types;


public class Rect {
    public Vec2 origin;
    public Size size;

    public Rect() {
        this(0, 0, 0, 0);
    }

    public Rect(final Vec2 origin, final Size size) {
        this(origin.x, origin.y, size.width, size.height);
    }
    
    private static final Rect ZERO_RECT = new Rect(0, 0, 0, 0);
    public static Rect getZero() {
    	return ZERO_RECT;
    }
    
    public static Rect zero() {
        return new Rect(0, 0, 0, 0);
    }

    public static Rect create(final Vec2 origin, final Size size) {
        return new Rect(origin.x, origin.y, size.width, size.height);
    }

    public static Rect create(float x, float y, float w, float h) {
        return new Rect(x, y, w, h);
    }
    
    public static Rect create(Rect r) {
    	return new Rect(r.origin, r.size);
    }

    private Rect(float x, float y, float w, float h) {
        origin = Vec2.create(x, y);
        size = Size.create(w, h);
    }
    
	public void set(Rect r) {
		origin.set(r.origin);
		size.set(r.size);
	}

	public void set(float x, float y, float w, float h) {
		origin.set(x, y);
		size.set(w, h);
	}
	public boolean isEmpty() {
        return (!(this.size.width > 0 && this.size.height > 0));
    }
	
	/* ---- Contains ---- */
    public boolean contains(float x, float y) {
        return size.width > 0 && size.height > 0  // check for empty first
                && x >= origin.x && x < (origin.x + size.width)
                && y >= origin.y && y < (origin.y + size.height);
    }
    public boolean contains(final Vec2 Vec2) {
        return ((Vec2.x >= minX(this))
                && (Vec2.y >= minY(this))
                && (Vec2.x < maxX(this))
                && (Vec2.y < maxY(this)));
    }
    public boolean contains(final Rect rect) {
        return (!rect.isEmpty()
                && (minX(this) <= minX(rect))
                && (minY(this) <= minY(rect))
                && (maxX(this) >= maxX(rect))
                && (maxY(this) >= maxY(rect)));
    }
    public boolean intersects(Rect rect)
    {
    	Rect a = this;
    	Rect b = rect;
    	return (a.origin.x >= (b.origin.x - a.size.width) && a.origin.x <= (b.origin.x - a.size.width) + (b.size.width + a.size.width)
    			&& a.origin.y >= (b.origin.y - a.size.height) && a.origin.y <= (b.origin.y - a.size.height) + (b.size.height + a.size.height));
    }
    public String toString() {
        return "((" + origin.x + ", " + origin.y + "),(" + size.width + ", " + size.height + "))";
    }

    public boolean equals(Rect rect) {
    	return this.origin.equals(rect.origin)&&this.size.equals(rect);
    }
  
    /**
     * Returns the greatest x-coordinate value still inside aRect.
     */
    public static float maxX(final Rect aRect) {
        return aRect.origin.x + aRect.size.width;
    }

    /**
     * Returns the greatest y-coordinate value still inside aRect.
     */
    public static float maxY(final Rect aRect) {
        return aRect.origin.y + aRect.size.height;
    }

    /**
     * Returns the x-coordinate of aRect's middle Vec2.
     */
    public static float midX(Rect aRect) {
        return aRect.origin.x + (float) (aRect.size.width / 2.0);
    }

    /**
     * Returns the y-coordinate of aRect's middle Vec2.
     */
    public static float midY(final Rect aRect) {
        return aRect.origin.y + (float) (aRect.size.height / 2.0);
    }

    /**
     * Returns the least x-coordinate value still inside aRect.
     */
    public static float minX(final Rect aRect) {
        return aRect.origin.x;
    }

    /**
     * Returns the least y-coordinate value still inside aRect.
     */
    public static float minY(final Rect aRect) {
        return aRect.origin.y;
    }

}
